package org.example;

import java.util.*;

/**
 * 30. 串联所有单词的子串
 *
 * 给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
 *
 * 注意子串要与 words 中的单词完全匹配，中间不能有其他字符，但不需要考虑 words 中单词串联的顺序。
 *
 *  
 *
 * 示例 1：
 *
 * 输入：
 *   s = "barfoothefoobarman",
 *   words = ["foo","bar"]
 * 输出：[0,9]
 * 解释：
 * 从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。
 * 输出的顺序不重要, [9,0] 也是有效答案。
 * 示例 2：
 *
 * 输入：
 *   s = "wordgoodgoodgoodbestword",
 *   words = ["word","good","best","word"]
 * 输出：[]
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
public class FindSubstringSolution {

    public List<Integer> findSubstring(String s, String[] words) {
        if (s == null || words == null || s.length() == 0 || words.length == 0) {
            return new ArrayList<>();
        }
        Set<Integer> resultList = new TreeSet<>();
        Set<String> contains = new TreeSet<>();
        for (int index = 0; index < words.length; index ++) {
            String cur = words[index];
            if (contains.contains(cur)) {
                continue;
            }
            contains.add(cur);
            List<String> other = getOtherList(index, words);
            resultList.addAll(obtainSubString(s, cur, other, words.length));
        }
        return new ArrayList<>(resultList);
    }

    private Set<Integer> obtainSubString(String s, String curStr, List<String> otherWords, int wordCount) {
        Set<Integer> emptySet = new TreeSet<>();
        int singleWordLen = curStr.length();
        int allWordLen = singleWordLen * wordCount;
        int from = 0;
        while (true) {
            int indexOf = s.indexOf(curStr, from);
            if (indexOf == -1) {
                return emptySet;
            }
            if (s.length() - indexOf < allWordLen) {
                return emptySet;
            }
            String mayBeStr = s.substring(indexOf, allWordLen + indexOf);
            int count = 1;
            int curIndex = count * singleWordLen;
            List<String> list = new ArrayList<>();
            while (count < wordCount) {
                list.add(mayBeStr.substring(curIndex, singleWordLen + curIndex));
                count ++;
                curIndex = count * singleWordLen;
            }
            Collections.sort(list);
            if (compare(list, otherWords)) {
                emptySet.add(indexOf);
            }
            from = indexOf + 1;
        }
    }

    private boolean compare(List<String> l1, List<String> l2) {
        if (l1.size() != l2.size()) {
            return false;
        }
        for (int index = 0; index < l1.size(); index ++) {
            String word01 = l1.get(index);
            String word02 = l2.get(index);
            if (!Objects.equals(word01, word02)) {
                return false;
            }
        }
        return true;
    }

    private List<String> getOtherList(int otherIndex, String[] words) {
        List<String> list = new ArrayList<>();
        for (int index = 0; index < words.length; index ++) {
            if (otherIndex != index) {
                list.add(words[index]);
            }
        }
        Collections.sort(list);
        return list;
    }




    public static void main(String[] args) {
        String s = "bcabbcaabbccacacbabccacaababcbb";
        String[] words = {"c","b","a","c","a","a","a","b","c"};
        FindSubstringSolution solution = new FindSubstringSolution();
        List<Integer> resultList = solution.findSubstring(s, words);
        System.out.println(resultList);
    }
}